package com.jacobson.huobi.common.expansion

import com.jacobson.core.framework.errorhandler.RxErrorHandler
import com.jacobson.core.framework.errorhandler.RxHandlerSubscriber
import com.jacobson.core.mvp.IView
import com.jacobson.huobi.Constants
import com.jacobson.huobi.entities.events.LoginEvent
import com.jacobson.huobi.entities.response.CommonResponse
import com.jacobson.huobi.entities.response.PageListResponse
import com.jacobson.huobi.entities.response.PageResponse
import com.jacobson.huobi.utils.RxSchedulersHelper
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import org.simple.eventbus.EventBus
import java.util.*

fun <T> io.reactivex.Observable<T>.applySchedulersIoMain(): io.reactivex.Observable<T> {
    return this.compose(RxSchedulersHelper.applySchedulersIoMain())
}

fun <T> Observable<T>.onResult(
    rxErrorHandler: RxErrorHandler,
    view: IView?,
    type: Int,
    extra: Any? = null,
    filter: ((success: Boolean) -> Unit)? = null,
    success: ((data: T) -> Unit)? = null
) {
    this.subscribe(rxErrorHandler.newRxHandlerSubscriber(view, type, extra, filter, success))
}

fun <T> Observable<T>.onResult(
    rxErrorHandler: RxErrorHandler,
    view: IView?,
    type: Int,
    extra: Any? = null,
    success: ((data: T) -> Unit)? = null
) {
    this.subscribe(rxErrorHandler.newRxHandlerSubscriber(view, type, extra, {
        view?.stopLoading(type, extra)
    }, success))
}

fun <T> RxErrorHandler.newRxHandlerSubscriber(
    view: IView?,
    type: Int,
    extra: Any? = null,
    filter: ((success: Boolean) -> Unit)? = null,
    success: ((data: T) -> Unit)? = null
): RxHandlerSubscriber<T> {
    return RxHandlerSubscriber.Builder<T>(this)
        .success { data -> success?.invoke(data) }
        .failure { code, message -> view?.onError(type, extra, code, message) ?: false }
        .postFilter { filter?.invoke(it) }
        .build()
}

fun <T : PageListResponse<*>> Observable<T>.onPageRespResult(
    view: IView?,
    success: (t: T) -> Unit
) {
    onPageRespResult(success) { code, msg ->
        view?.onError(code = code, message = msg)
    }
}

fun <T : PageListResponse<*>> Observable<T>.onPageRespResult(
    success: (t: T) -> Unit,
    failure: (code: Int, msg: String) -> Unit
) {
    this.subscribe(object : Observer<T> {
        override fun onComplete() {

        }

        override fun onSubscribe(d: Disposable) {

        }

        override fun onNext(t: T) {
            if (t.code == Constants.RESP_OK) {
                success.invoke(t)
            }
//            else if (t.code == Constants.RESP_CREDENTIALS_EXPIRED) {
//                EventBus.getDefault().post(LoginEvent(2, null))
//            }
            else {
                failure.invoke(t.code, t.msg)
            }
        }

        override fun onError(e: Throwable) {
            failure.invoke(Constants.ERROR_RESP, e.message.toString())
        }
    })
}


fun <T : PageResponse<*>> Observable<T>.onRespResult(
    view: IView?,
    success: (t: T) -> Unit
) {
    onRespResult(success) { code, msg ->
        view?.onError(code = code, message = msg)
    }
}

fun <T : PageResponse<*>> Observable<T>.onRespResult(
    success: (t: T) -> Unit,
    failure: (code: Int, msg: String) -> Unit
) {
    this.subscribe(object : Observer<T> {
        override fun onComplete() {

        }

        override fun onSubscribe(d: Disposable) {

        }

        override fun onNext(t: T) {
            if (t.code == Constants.RESP_OK) {
                success.invoke(t)
            }
//            else if (t.code == Constants.RESP_CREDENTIALS_EXPIRED) {
//                EventBus.getDefault().post(LoginEvent(2, null))
//            }
            else {
                failure.invoke(t.code, t.msg)
            }
        }

        override fun onError(e: Throwable) {
            failure.invoke(Constants.ERROR_RESP, e.message.toString())
        }
    })
}



fun <T :CommonResponse<*>> Observable<T>.onResponseResult(
    success: (t: T) -> Unit,
    failure: (code: Int, msg: String) -> Unit
) {
    this.subscribe(object : Observer<T> {
        override fun onComplete() {

        }

        override fun onSubscribe(d: Disposable) {

        }

        override fun onNext(t: T) {
            if (t.code != null) {
                if (t.code == Constants.RESP_CREDENTIALS_EXPIRED) {
//                    EventBus.getDefault().post(LoginEvent(2, null))
                }
                success.invoke(t)
            } else {
                failure.invoke(t.code, t.msg)
            }
        }

        override fun onError(e: Throwable) {
            failure.invoke(Constants.ERROR_RESP, e.message.toString())
        }
    })
}

fun <T : CommonResponse<*>> Observable<T>.onResponseResult(
    view: IView?,
    success: (t: T) -> Unit
) {
    onResponseResult(success) { code, msg ->
        view?.onError(code = code, message = msg)
    }
}